package com.pushtime.service;

import java.util.List;

import javax.persistence.criteria.JoinType;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import io.github.jhipster.service.QueryService;

import com.pushtime.domain.HdfsLog;
import com.pushtime.domain.*; // for static metamodels
import com.pushtime.repository.HdfsLogRepository;
import com.pushtime.service.dto.HdfsLogCriteria;
import com.pushtime.service.dto.HdfsLogDTO;
import com.pushtime.service.mapper.HdfsLogMapper;

/**
 * Service for executing complex queries for HdfsLog entities in the database.
 * The main input is a {@link HdfsLogCriteria} which gets converted to {@link Specification},
 * in a way that all the filters must apply.
 * It returns a {@link List} of {@link HdfsLogDTO} or a {@link Page} of {@link HdfsLogDTO} which fulfills the criteria.
 */
@Service
@Transactional(readOnly = true)
public class HdfsLogQueryService extends QueryService<HdfsLog> {

    private final Logger log = LoggerFactory.getLogger(HdfsLogQueryService.class);

    private final HdfsLogRepository hdfsLogRepository;

    private final HdfsLogMapper hdfsLogMapper;

    public HdfsLogQueryService(HdfsLogRepository hdfsLogRepository, HdfsLogMapper hdfsLogMapper) {
        this.hdfsLogRepository = hdfsLogRepository;
        this.hdfsLogMapper = hdfsLogMapper;
    }

    /**
     * Return a {@link List} of {@link HdfsLogDTO} which matches the criteria from the database
     * @param criteria The object which holds all the filters, which the entities should match.
     * @return the matching entities.
     */
    @Transactional(readOnly = true)
    public List<HdfsLogDTO> findByCriteria(HdfsLogCriteria criteria) {
        log.debug("find by criteria : {}", criteria);
        final Specification<HdfsLog> specification = createSpecification(criteria);
        return hdfsLogMapper.toDto(hdfsLogRepository.findAll(specification));
    }

    /**
     * Return a {@link Page} of {@link HdfsLogDTO} which matches the criteria from the database
     * @param criteria The object which holds all the filters, which the entities should match.
     * @param page The page, which should be returned.
     * @return the matching entities.
     */
    @Transactional(readOnly = true)
    public Page<HdfsLogDTO> findByCriteria(HdfsLogCriteria criteria, Pageable page) {
        log.debug("find by criteria : {}, page: {}", criteria, page);
        final Specification<HdfsLog> specification = createSpecification(criteria);
        return hdfsLogRepository.findAll(specification, page)
            .map(hdfsLogMapper::toDto);
    }

    /**
     * Return the number of matching entities in the database
     * @param criteria The object which holds all the filters, which the entities should match.
     * @return the number of matching entities.
     */
    @Transactional(readOnly = true)
    public long countByCriteria(HdfsLogCriteria criteria) {
        log.debug("count by criteria : {}", criteria);
        final Specification<HdfsLog> specification = createSpecification(criteria);
        return hdfsLogRepository.count(specification);
    }

    /**
     * Function to convert HdfsLogCriteria to a {@link Specification}
     */
    private Specification<HdfsLog> createSpecification(HdfsLogCriteria criteria) {
        Specification<HdfsLog> specification = Specification.where(null);
        if (criteria != null) {
            if (criteria.getId() != null) {
                specification = specification.and(buildSpecification(criteria.getId(), HdfsLog_.id));
            }
            if (criteria.getName() != null) {
                specification = specification.and(buildStringSpecification(criteria.getName(), HdfsLog_.name));
            }
            if (criteria.getSrc() != null) {
                specification = specification.and(buildStringSpecification(criteria.getSrc(), HdfsLog_.src));
            }
            if (criteria.getDst() != null) {
                specification = specification.and(buildStringSpecification(criteria.getDst(), HdfsLog_.dst));
            }
            if (criteria.getTotalSize() != null) {
                specification = specification.and(buildRangeSpecification(criteria.getTotalSize(), HdfsLog_.totalSize));
            }
            if (criteria.getCurrentSize() != null) {
                specification = specification.and(buildRangeSpecification(criteria.getCurrentSize(), HdfsLog_.currentSize));
            }
            if (criteria.getProcess() != null) {
                specification = specification.and(buildRangeSpecification(criteria.getProcess(), HdfsLog_.process));
            }
            if (criteria.getState() != null) {
                specification = specification.and(buildRangeSpecification(criteria.getState(), HdfsLog_.state));
            }
            if (criteria.getDesc() != null) {
                specification = specification.and(buildStringSpecification(criteria.getDesc(), HdfsLog_.desc));
            }
            if (criteria.getCreatedDate() != null) {
                specification = specification.and(buildRangeSpecification(criteria.getCreatedDate(), HdfsLog_.createdDate));
            }
        }
        return specification;
    }
}
